import { beforeEach, describe, expect, it, vi } from "vitest";

import { defaultPreferences } from "../src/config";
import { PreferenceManager } from "../src/preferences";
import { isDarkTheme } from "../src/update-css-variables";

describe("preferences", () => {
  let preferenceManager: PreferenceManager;

  // 模拟 window.matchMedia 方法
  vi.stubGlobal(
    "matchMedia",
    vi.fn().mockImplementation((query) => ({
      addEventListener: vi.fn(),
      addListener: vi.fn(), // Deprecated
      dispatchEvent: vi.fn(),
      matches: query === "(prefers-color-scheme: dark)",
      media: query,
      onchange: null,
      removeEventListener: vi.fn(),
      removeListener: vi.fn(), // Deprecated
    })),
  );
  beforeEach(() => {
    preferenceManager = new PreferenceManager();
  });

  it("loads default preferences if no saved preferences found", () => {
    const preferences = preferenceManager.getPreferences();
    expect(preferences).toEqual(defaultPreferences);
  });

  it("initializes preferences with overrides", async () => {
    const overrides: any = {
      app: {
        locale: "en-US",
      },
    };
    await preferenceManager.initPreferences({
      namespace: "testNamespace",
      overrides,
    });

    // 等待防抖动操作完成
    // await new Promise((resolve) => setTimeout(resolve, 300)); // 等待100毫秒

    const expected = {
      ...defaultPreferences,
      app: {
        ...defaultPreferences.app,
        ...overrides.app,
      },
    };

    expect(preferenceManager.getPreferences()).toEqual(expected);
  });

  it("updates theme mode correctly", () => {
    preferenceManager.updatePreferences({
      theme: {
        mode: "light",
      },
    });

    expect(preferenceManager.getPreferences().theme.mode).toBe("light");
  });

  it("updates color modes correctly", () => {
    preferenceManager.updatePreferences({
      app: { colorGrayMode: true, colorWeakMode: true },
    });

    expect(preferenceManager.getPreferences().app.colorGrayMode).toBe(true);
    expect(preferenceManager.getPreferences().app.colorWeakMode).toBe(true);
  });

  it("resets preferences to default", () => {
    // 先更新一些偏好设置
    preferenceManager.updatePreferences({
      theme: {
        mode: "light",
      },
    });

    // 然后重置偏好设置
    preferenceManager.resetPreferences();

    expect(preferenceManager.getPreferences()).toEqual(defaultPreferences);
  });

  it("updates isMobile correctly", () => {
    // 模拟移动端状态
    vi.stubGlobal(
      "matchMedia",
      vi.fn().mockImplementation((query) => ({
        addEventListener: vi.fn(),
        addListener: vi.fn(),
        dispatchEvent: vi.fn(),
        matches: query === "(max-width: 768px)",
        media: query,
        onchange: null,
        removeEventListener: vi.fn(),
        removeListener: vi.fn(),
      })),
    );

    preferenceManager.updatePreferences({
      app: { isMobile: true },
    });

    expect(preferenceManager.getPreferences().app.isMobile).toBe(true);
  });

  it("updates the locale preference correctly", () => {
    preferenceManager.updatePreferences({
      app: { locale: "en-US" },
    });

    expect(preferenceManager.getPreferences().app.locale).toBe("en-US");
  });

  it("updates the sidebar width correctly", () => {
    preferenceManager.updatePreferences({
      sidebar: { width: 200 },
    });

    expect(preferenceManager.getPreferences().sidebar.width).toBe(200);
  });
  it("updates the sidebar collapse state correctly", () => {
    preferenceManager.updatePreferences({
      sidebar: { collapsed: true },
    });

    expect(preferenceManager.getPreferences().sidebar.collapsed).toBe(true);
  });
  it("updates the navigation style type correctly", () => {
    preferenceManager.updatePreferences({
      navigation: { styleType: "flat" },
    } as any);

    expect(preferenceManager.getPreferences().navigation.styleType).toBe(
      "flat",
    );
  });

  it("resets preferences to default correctly", () => {
    // 先更新一些偏好设置
    preferenceManager.updatePreferences({
      app: { locale: "en-US" },
      sidebar: { collapsed: true, width: 200 },
      theme: {
        mode: "light",
      },
    });

    // 然后重置偏好设置
    preferenceManager.resetPreferences();

    expect(preferenceManager.getPreferences()).toEqual(defaultPreferences);
  });

  it("does not update undefined preferences", () => {
    const originalPreferences = preferenceManager.getPreferences();

    preferenceManager.updatePreferences({
      app: { nonexistentField: "value" },
    } as any);

    expect(preferenceManager.getPreferences()).toEqual(originalPreferences);
  });

  it("reverts to default when a preference field is deleted", () => {
    preferenceManager.updatePreferences({
      app: { locale: "en-US" },
    });

    preferenceManager.updatePreferences({
      app: { locale: undefined },
    });

    expect(preferenceManager.getPreferences().app.locale).toBe("en-US");
  });

  it("ignores updates with invalid preference value types", () => {
    const originalPreferences = preferenceManager.getPreferences();

    preferenceManager.updatePreferences({
      app: { isMobile: "true" as unknown as boolean }, // 错误类型
    });

    expect(preferenceManager.getPreferences()).toEqual(originalPreferences);
  });

  it("merges nested preference objects correctly", () => {
    preferenceManager.updatePreferences({
      app: { name: "New App Name" },
    });

    const expected = {
      ...defaultPreferences,
      app: {
        ...defaultPreferences.app,
        name: "New App Name",
      },
    };

    expect(preferenceManager.getPreferences()).toEqual(expected);
  });

  it("applies updates immediately after initialization", async () => {
    const overrides: any = {
      app: {
        locale: "en-US",
      },
    };

    await preferenceManager.initPreferences(overrides);

    preferenceManager.updatePreferences({
      theme: { mode: "light" },
    });

    expect(preferenceManager.getPreferences().theme.mode).toBe("light");
  });
});

describe("isDarkTheme", () => {
  it("should return true for dark theme", () => {
    expect(isDarkTheme("dark")).toBe(true);
  });

  it("should return false for light theme", () => {
    expect(isDarkTheme("light")).toBe(false);
  });

  it("should return system preference for auto theme", () => {
    vi.spyOn(window, "matchMedia").mockImplementation((query) => ({
      addEventListener: vi.fn(),
      addListener: vi.fn(), // Deprecated
      dispatchEvent: vi.fn(),
      matches: query === "(prefers-color-scheme: dark)",
      media: query,
      onchange: null,
      removeEventListener: vi.fn(),
      removeListener: vi.fn(), // Deprecated
    }));

    expect(isDarkTheme("auto")).toBe(true);
    expect(window.matchMedia).toHaveBeenCalledWith(
      "(prefers-color-scheme: dark)",
    );
  });
});
